import {
  Renderer,
  renderFilterDropdownItem,
  renderFilterDropdownTabs,
  renderInputDropdownItem,
  renderInputDropdownHeader,
  renderVisualSearchTerm,
  itemDivider,
  renderSearchTip
} from './render'
import { bindIntent, stopIntent } from './event'

export class Builder extends Renderer {
  /**
   * 构建筛选器的下拉菜单选项
   * @param {Object} filter 筛选器对象
   */
  buildFilterDropdownItems(filter) {
    var that = this
    var item = {}

    that.$inputDropdownMenu.empty()
    // 如果条件支持多选，则添加一条选项，让用户点击退出此条件的选择
    if (filter.multiple) {
      that.$inputDropdownMenu.append(
        renderInputDropdownItem({
          key: '<cmd:back>',
          icon: 'icon angle double left',
          class: 'item-fixed',
          name: that.text.selectOtherFilter
        }),
        itemDivider
      )
    }
    // 如果有设置“无“选项
    if (typeof filter.none === 'object') {
      Object.keys(filter.none).forEach(function (k) {
        item[k] = filter.none[k]
      })
      if (item.class) {
        item.class = `${item.class} item-fixed`
      } else {
        item.class = 'item-fixed'
      }
      that.$inputDropdownMenu.append(
        renderFilterDropdownItem(item),
        itemDivider
      )
    }
    if (filter.tabs && filter.tabs.length) {
      that.$inputDropdownMenu.append(renderFilterDropdownTabs(filter.tabs))
    }
    this.getFilterAvailableItems(filter).forEach(function (filterItem) {
      that.$inputDropdownMenu.append(renderFilterDropdownItem(filterItem))
    })
    if (filter.searchOption) {
      that.$inputDropdownMenu.append(renderSearchTip(filter.searchOption.searchTip))
    }
    if (filter.tabs && filter.tabs.length) {
      that.$el.find(`.tab[data-tab=${filter.tabs[0].key}]`).addClass('active')
      that.$inputDropdownMenu.find('.item').addClass('hide')
      that.$inputDropdownMenu.find(`.item[data-tab=${filter.tabs[0].key}]`).removeClass('hide')
    }
    that.$inputDropdown.dropdown('refresh').dropdown('search') // .dropdown('search') 防止远程结果为空时下拉框显示有问题
  }

  buildRemoteSearchDropdownItems(key, items) {
    this.$inputDropdownMenu.find(`.item[data-tab=${key}]`).remove()
    items.forEach((filterItem) => {
      this.$inputDropdownMenu.append(renderFilterDropdownItem(filterItem))
    })
  }

  buildSearchTip(searchTip) {
    this.$inputDropdownMenu.append(renderSearchTip(searchTip))
  }

  buildFilterDropdownRemoteTabItems(filter) {
    var that = this
    that.$inputDropdownMenu.empty().append(
      renderInputDropdownItem({
        key: '<cmd:wait>',
        icon: 'ui active inline mini loader',
        class: 'item-fixed',
        name: that.text.loading,
        type: filter.type
      })
    )
    that.loadFilterRemoteItems(filter, function () {
      if (that.target && that.target.key === filter.key) {
        that.buildFilterDropdownItems(filter)
      }
    })
  }

  buildFilterDropdownRemoteItems(filter) {
    var that = this
    that.$inputDropdownMenu.empty().append(
      renderInputDropdownItem({
        key: '<cmd:wait>',
        icon: 'ui active inline mini loader',
        class: 'item-fixed',
        name: that.text.loading,
        type: filter.type
      })
    )
    that.loadFilterRemoteItems(filter, function () {
      if (that.target && that.target.key === filter.key) {
        that.buildFilterDropdownItems(filter)
      }
    })
  }

  /**
   * 构建时间范围选择器
   * @param {Object} filter 筛选器对象
   */
  buildDateRangePicker(filter) {
    var picker
    var that = this
    var value = this.targetValue
    var values

    that.$inputDropdown.dropdown({
      on: 'custom',
      onShow: function () {
        return false
      }
    }).dropdown('hide')
    that.removeDateRangePicker()
    that.$input.daterangepicker(filter.config)
    picker = that.$input.data('daterangepicker')
    if (value) {
      values = value.split(picker.locale.separator)
      picker.setStartDate(values[0])
      picker.setEndDate(values[1])
    }
    that.$input.on({
      'apply.daterangepicker': function () {
        var start = picker.startDate.format(picker.locale.format)
        var end = picker.endDate.format(picker.locale.format)
        that.selectFilterValue(start + picker.locale.separator + end)
        that.clearTargetFilter()
        that.$input.val('')
        picker.remove()
      },
      'cancel.daterangepicker': function () {
        that.selectFilterValue(value)
        that.clearTargetFilter()
        that.$input.val('')
        picker.remove()
      }
    })
    picker.show()
  }

  /**
   * 构建筛选器的下拉框，列出当前筛选器的可选选项
   * @param {Object} filter 筛选器对象
   */
  buildFilterDropdown(filter) {
    var that = this

    that.updatePlaceholder()
    if (filter.type === 'daterange') {
      this.buildDateRangePicker(filter)
      return
    }
    if(filter.tabs && filter.tabs.length) {
      this.$tokens.find('.menu.transition.visible').addClass('with-tabs')
      that.buildFilterDropdownRemoteTabItems(filter)
    } else {
      this.$tokens.find('.menu.transition.visible').removeClass('with-tabs')
      if (typeof filter.remote === 'object') {
        that.buildFilterDropdownRemoteItems(filter)
      } else {
        that.buildFilterDropdownItems(filter)
      }
    }
    that.$inputDropdown
      .removeClass('input-filter-token')
      .addClass('input-filter-value-token')
      .dropdown({
        forceSelection: false,
        fullTextSearch: true,
        selectOnKeydown: false,
        onHide: function () {
          that.logger.log('buildFilterDropdown() hide?', !that.hasFocus())
          // 根据当前状态确定是否阻止隐藏下拉框
          return that.onHide()
        },
        action: function (_text, value) {
          var item

          that.lockShow()

          if (!value) {
            return true
          }
          if (that.execCommand(value)) {
            return true
          }
          that.input = ''
          that.targetValue = ''
          if ((typeof filter.none === 'object')
          && filter.none.value.toString() === value) {
            that.clearFilterValue()
            that.selectFilterValue(value)
            that.clearTargetFilter()
            return false
          }
          item = that.getCurrentFilterItem(value)
          if (item) {
            that.selectFilterValue(value)
          }
          // 如果是多选，则重置下拉框
          if (filter.multiple) {
            // 没有可选选项就退出编辑筛选器
            if (!that.visibleFilter(filter)) {
              that.clearTargetFilter()
            } else {
              that.buildFilterDropdown(filter)
              that.$input.val('')
              that.$input.focus()
              if (filter.tabs) {
                that.setTabSelected()
              }
            }
          } else {
            that.clearTargetFilter()
          }
          stopIntent(that)
          return false
        },
        onChange: function (value) {
          var item

          that.lockShow()
          if (value && value.indexOf('<cmd:') === 0) {
            return
          }
          item = that.getCurrentFilterItem(value)
          if (item) {
            that.$input.val(item.name)
          }
        }
      }).dropdown('clear')

    this.logger.log('[' + filter.key + ']', 'buildFilterDropdown()')
  }

  /**
   * 构建已分组的下拉菜单选项
   * @param {Array} 分组参数列表
   * @returns {Array} 已被分组的筛选器的 key 列表
   */
  buildGroupedDropdownItems(groups) {
    var that = this
    var groupedFilters = []

    groups.forEach(function (group) {
      var html = ''

      that.filters.forEach(function (filter) {
        if (group.keys.indexOf(filter.key) < 0) {
          return
        }
        groupedFilters.push(filter.key)
        if (!that.visibleFilter(filter)) {
          return
        }
        html += renderInputDropdownItem(filter)
      })
      if (html) {
        html = renderInputDropdownHeader(group.name) + html
      }
      that.$inputDropdownMenu.append(html)
    })
    return groupedFilters
  }

  buildHistoryItems() {
    if (this.config.history && this.history.load().length > 0) {
      this.$inputDropdownMenu.append(
        renderInputDropdownHeader(this.text.history),
        this.history.render(),
        renderInputDropdownItem({
          key: '<cmd:clear-history>',
          name: this.text.clearHistory
        }),
        itemDivider
      )
    }
  }

  clearSearchItem() {
    this.$input.off('input.dropdown')
  }

  // 构建“搜索”选项
  buildSearchItem() {
    var that = this
    var $cmd = $(renderInputDropdownItem({
      key: '<cmd:search>',
      icon: 'icon search',
      class: 'item-fixed',
      name: that.text.searchHelp
    }))

    that.$inputDropdownMenu.append($cmd)
    // 在输入内容时，更新“搜索”选项的值，让下拉框能将它作为第一个匹配的选项，并默认选中它
    that.$input.on('input.dropdown', function () {
      // 将输入框当前值放在前面，确保下拉框能够搜索匹配到
      $cmd.attr('data-value', that.$input.val() + ';<cmd:search>')
      that.$inputDropdown.dropdown('refresh')
    })
  }

  buildInputDropdown() {
    var html = ''
    var that = this
    var groupedFilters = []

    this.clearSearchItem()
    if (that.target) {
      that.buildFilterDropdown(that.target)
      return
    }
    that.updatePlaceholder()
    that.logger.log('buildInputDropdown()')
    that.$inputDropdownMenu.empty()
    that.buildSearchItem()
    that.buildHistoryItems()
    if (that.groups.length > 0) {
      groupedFilters = that.buildGroupedDropdownItems(that.groups)
    }
    that.filters.forEach(function (filter) {
      if (groupedFilters.indexOf(filter.key) >= 0) {
        return
      }
      if (!that.visibleFilter(filter)) {
        return
      }
      html += renderInputDropdownItem(filter)
    })
    if (html && groupedFilters.length > 0) {
      html = itemDivider + html
    }
    that.$inputDropdownMenu.append(html)
    that.$inputDropdown
      .addClass('input-filter-token')
      .removeClass('input-filter-value-token')
      .dropdown({
        forceSelection: false,
        selectOnKeydown: false,
        onHide: function () {
          if (that.input) {
            that.applyInput()
          }
          if (!that.hasFocus()) {
            that.resetInputPosition()
          }
          that.logger.log('buildInputDropdown() hide?', !that.hasFocus())
          return that.onHide()
        },
        action: function (_text, value) {
          that.logger.log('action():', value)
          that.lockShow()

          if (value) {
            if (that.newFilter(value)) {
              return
            }
          }
          if (that.input) {
            that.applyInput()
            that.buildInputDropdown()
            that.execCommand(value)
          } else if (that.execCommand(value)) {
            // 清空下拉框的值，以取消选项的“已选中”的效果
            that.$inputDropdown.dropdown('clear')
            that.logger.log('execCommand')
            that.applyInput()
          }
        }
      }).dropdown('clear')
  }

  // 构建已选中的筛选器标记
  buildFilterTokens() {
    var that = this

    that.loadingFilters = 0
    that.filters.forEach(function (filter) {
      var html
      var value = that.data[filter.key]

      that.logger.log('buildFilterTokens():', filter.key)
      if (typeof value === 'undefined') {
        return
      }
      if (filter.multiple) {
        if (value.length < 1) {
          return
        }
      } else if (value === '') {
        return
      }
      if (that.checkFilterItemsLoaded(filter)) {
        html = that.renderVisualToken(filter, value)
        $(html).insertBefore(that.$inputDropdown)
        return
      }
      that.setDisabled(true)
      that.loadingFilters += 1
      that.loadFilterRemoteItems(filter, function () {
        var selector = '.js-visual-token[data-key="' + filter.key + '"]'

        that.$el.find(selector).remove()
        html = that.renderVisualToken(filter, that.data[filter.key])
        $(html).insertBefore(that.$inputDropdown)
        that.loadingFilters -= 1
        if (that.loadingFilters < 1) {
          that.setDisabled(false)
          that.buildSearchTerm()
        }
      })
    })
  }

  // 更新搜索条件的内容及位置
  buildSearchTerm() {
    if (this.$search && this.$search.length > 0) {
      if (this.data.search) {
        this.$search.find('.name').text(this.data.search)
      } else {
        this.$search.remove()
        this.$search = null
        return
      }
    } else if (this.data.search) {
      this.$search = $(renderVisualSearchTerm({ value: this.data.search }))
    } else {
      return
    }
    // 移动元素时会触发下拉框的 hide 行为，而 onHide() 回调里有调用 applyInput() 方法，
    // 等于递归调用了一次，为避免重复记录搜索词，在这里加个延迟
    setTimeout(function () {
      // 顺带更新条件和输入框的位置
      this.deferFocusTime()
      this.$tokens.append(this.$search, this.$inputDropdown)
    }.bind(this))
  }

  // 构建组件基础内容和功能
  build() {
    this.$el.html(this.renderBody())
    this.$el.addClass('filtered-search-box')
    this.$tokens = this.$el.find('.tokens-container')
    this.$input = this.$el.find('.filtered-search')
    this.$inputDropdown = this.$input.parent()
    this.$inputDropdownMenu = this.$inputDropdown.find('.filter-items')
    this.$btnClearSearch = this.$el.find('.clear-search')
    this.buildInputDropdown()
    this.buildFilterTokens()
    this.buildSearchTerm()
    bindIntent(this)
    this.updateClearButton()
  }
}

export default Builder
